package com.robusta.app.model.spreadsheet;

import com.robusta.spreadsheet.model.*;
import com.robusta.spreadsheet.model.exception.WorkbookException;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;

public class WorkbookModelMatchers {
    public static Matcher<SheetHeaders> hasHeaderCell(final int position, final Matcher<HeaderCell> headerCellMatcher) {
        return new TypeSafeMatcher<SheetHeaders>() {
            @Override
            public boolean matchesSafely(SheetHeaders headerCells) {
                HeaderCell headerCell;
                try {
                    headerCell = headerCells.getHeaderAt(position);
                    return headerCell != null && headerCellMatcher.matches(headerCell);
                } catch (WorkbookException e) {
                    throw new RuntimeException(e);
                }
            }

            @Override
            public void describeTo(Description description) {
                description
                        .appendText("with valid header cell at position: ")
                        .appendValue(position).appendText(" and ");
                headerCellMatcher.describeTo(description);
            }
        };
    }

    public static Matcher<HeaderCell> withHeaderText(final String text) {
        return new TypeSafeMatcher<HeaderCell>() {
            @Override
            public boolean matchesSafely(HeaderCell headerCell) {
                return headerCell.getText().equals(text);
            }

            @Override
            public void describeTo(Description description) {
                description
                        .appendText("Header cell text equals to: ")
                        .appendValue(text);
            }
        };
    }

    public static Matcher<Cell> withCellValue(final String cellValue) {
        return new TypeSafeMatcher<Cell>() {
            @Override
            public boolean matchesSafely(Cell cell) {
                return cellValue.equals(cell.getValue());
            }

            @Override
            public void describeTo(Description description) {
                description.appendText("with cell value equal to: ")
                        .appendValue(cellValue);
            }
        };
    }

    public static Matcher<Row> withCellWithHeaderText(final String headerText, final Matcher<Cell> cellMatcher) {
        return new TypeSafeMatcher<Row>() {
            @Override
            public boolean matchesSafely(Row row) {
                try {
                    return cellMatcher.matches(row.getCellByHeaderText(headerText));
                } catch (WorkbookException e) {
                    return false;
                }
            }

            @Override
            public void describeTo(Description description) {
                description
                        .appendText("with valid cell matching header text: ")
                        .appendValue(headerText).appendText(" and ");
                cellMatcher.describeTo(description);
            }
        };
    }

    public static Matcher<Worksheet> hasRowAt(final int rowIndex, final Matcher<Row> rowMatcher) {
        return new TypeSafeMatcher<Worksheet>() {

            @Override
            public boolean matchesSafely(Worksheet sheet) {
                return rowMatcher.matches(sheet.getRowAt(rowIndex));
            }

            @Override
            public void describeTo(Description description) {
                description
                        .appendText("with valid row at row index: ")
                        .appendValue(rowIndex).appendText(" and ");
                rowMatcher.describeTo(description);
            }
        };
    }
}
